package com.hicorp.segment.service.impl;

import com.hicorp.segment.mapper.*;
import com.hicorp.segment.pojo.po.*;
import com.hicorp.segment.mapper.MenuMapper;
import com.hicorp.segment.mapper.RoleMenuRelationMapper;
import com.hicorp.segment.mapper.UserMapper;
import com.hicorp.segment.pojo.bo.UserChangePassword;
import com.hicorp.segment.security.utils.SecurityUtils;
import com.hicorp.segment.service.AuthorityService;
import com.hicorp.segment.utils.ResultBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @Author:
 * @Date: Created in 4:24 2021/5/19
 * @Description:
 * @ChineseDescription:
 * @Modified_By:
 */
@Service("userService")
@Slf4j
public class AuthorityServiceImpl implements AuthorityService {
    @Resource
    private UserMapper userMapper;

    @Resource
    private MenuMapper menuMapper;

    @Resource
    private BackendApiMapper backendApiMapper;

    @Resource
    private MenuBackendApiRelationMapper menuBackendApiRelationMapper;

    @Resource
    private MenuResourceRelationMapper menuResourceRelationMapper;

    @Resource
    private RoleMenuRelationMapper roleMenuRelationMapper;

    @Resource
    private RoleBackendApiRelationMapper roleBackendApiRelationMapper;


    @Resource
    private UserRoleRelationMapper userRoleRelationMapper;

    private final SecurityUtils securityUtils;

    public AuthorityServiceImpl(SecurityUtils securityUtils) {
        this.securityUtils = securityUtils;
    }

    @Override
    public User getUser(String username) {
        return userMapper.findByUserName(username);
    }


    /**
     * 用户注册
     *
     * @param user 前端传来的用户信息
     * @return 标准返还
     */
    @Override
    public ResultBean<Void> register(User user) {
        try {
            String str1 = "000" + (Integer.parseInt(userMapper.findLastUserNO()) + 1);
            String returnNO = str1.substring(str1.length() - 4);
            user.setUserNo(returnNO);
            PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            user.setPassword(passwordEncoder.encode("123456"));
            userMapper.insert(user);
            return new ResultBean<>();
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, "用户添加失败!");
        }
    }

    /**
     * 查询所有的菜单(返回树形结构)
     *
     * @return 返回树形结构
     */
    @Override
    public ResultBean<List<Menu>> selectAllMenuTree() {
        List<Menu> menuList = menuMapper.selectAll();
        try {
            List<Menu> menuTree =
                    menuList
                            .stream()
                            .filter(menu -> menu.getParentId() != null)
                            .filter(menu -> 1 == menu.getParentId())
                            .peek(menu -> menu.setChildren(getMenuChildren(menu, menuList)))
                            .collect(Collectors.toList());
            return new ResultBean<>(menuTree);
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, "查询菜单错误,请联系管理员!");
        }
    }

    /**
     * 设置角色可访问的菜单
     *
     * @param roleMenuRelations 角色菜单关系
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultBean<Void> setRoleMenuRelation(List<RoleMenuRelation> roleMenuRelations) {
        try {
            Long roleId = roleMenuRelations.get(0).getRoleId();
            List<Long> menuIds = roleMenuRelationMapper.selectMenuIdByRoleId(roleId);
            if (!menuIds.isEmpty()) {
                roleMenuRelationMapper.deleteByRoleId(roleId);
            }
            if(roleMenuRelations.get(0).getMenuId()!=-1)
            roleMenuRelationMapper.insertList(roleMenuRelations);
            return new ResultBean<>();
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, "设置权限失败!");
        }
    }
    /**
     * 设置角色可访问的BackendApi
     * @param roleBackendApiRelations 角色api关系
     * @return 是否成功
     */
    @Override
    public ResultBean<Void> setRoleBackendApiRelation(List<RoleBackendApiRelation> roleBackendApiRelations) {
        try {
            Long roleId = roleBackendApiRelations.get(0).getRoleId();
            List<Long> menuIdList = roleMenuRelationMapper.selectMenuIdByRoleId(roleId);
            List<Long> resourceApiList=selectResourceByMenuId(menuIdList);
            List<RoleBackendApiRelation> newRoleBackendApiRelations=roleBackendApiRelations
                    .stream()
                    .filter(roleBackendApiRelation -> 0 < roleBackendApiRelation.getBackendApiId())
                    .collect(Collectors.toList());
            List<RoleBackendApiRelation> roleResourceApiRelations=resourceApiList.
                    stream()
                    .map((item)->{
                        RoleBackendApiRelation roleBackendApiRelation=new RoleBackendApiRelation();
                        roleBackendApiRelation.setBackendApiId(item);
                        roleBackendApiRelation.setRoleId(roleId);
                        return roleBackendApiRelation;
                    })
                    .collect(Collectors.toList());
            List<Long> backendApiIds = roleBackendApiRelationMapper.selectBackendApiIdByRoleId(roleId);
            if (!backendApiIds.isEmpty()) {
                roleBackendApiRelationMapper.deleteByRoleId(roleId);
            }
            if(roleBackendApiRelations.get(0).getBackendApiId()!=-1){
                roleBackendApiRelationMapper.insertList(newRoleBackendApiRelations);
            }
            roleBackendApiRelationMapper.insertList(roleResourceApiRelations);
            return new ResultBean<>();
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, "设置权限失败!");
        }
    }

    @Override
    public ResultBean<Void> setMenuBackendApiRelation(List<MenuBackendApiRelation> menuBackendApiRelationList) {
        try {
            Long menuId = menuBackendApiRelationList.get(0).getMenuId();
            List<BackendApi> backendApiIds = menuBackendApiRelationMapper.selectBackendApiListByMenuId(menuId);
            if (!backendApiIds.isEmpty()) {
                menuBackendApiRelationMapper.deleteByMenuId(menuId);
            }
            menuBackendApiRelationMapper.insertList(menuBackendApiRelationList);
            return new ResultBean<>();
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, "设置权限失败!");
        }
    }

    /**
     * 设置用户角色
     *
     * @param userRoleRelations 用户角色关系
     * @return 是否成功
     */
    @Override
    public ResultBean<Void> setUserRoleRelation(List<UserRoleRelation> userRoleRelations) {
        try {
            Long userId = userRoleRelations.get(0).getUserId();
            List<Long> roleIds = userRoleRelationMapper.selectRoleIdByUserId(userId);
            if (!roleIds.isEmpty()) {
                userRoleRelationMapper.deleteByUserId(userId);
            }
            userRoleRelationMapper.insertList(userRoleRelations);
            return new ResultBean<>();
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, "设置用户角色失败!");
        }
    }

    /**
     * 根据角色id查询其可访问的菜单的id
     *
     * @param roleId 角色id
     * @return 可访问的菜单的id
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultBean<List<Long>> selectMenuIdByRoleId(Long roleId) {
        try {
            List<Long> menuIdList = roleMenuRelationMapper.selectMenuIdByRoleId(roleId);
            return new ResultBean<>(menuIdList);
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, "查询角色可访问的菜单失败!");
        }
    }

    @Override
    public ResultBean<List<Long>> selectBackendAPiIdByRoleId(Long roleId) {
        try {
            List<Long> backendApiIdList = roleBackendApiRelationMapper.selectBackendApiIdByRoleId(roleId)
                    .stream()
                    .map(backendApi->backendApi+10000)
                    .collect(Collectors.toList());
            System.out.println(backendApiIdList);
            return new ResultBean<>(backendApiIdList);
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, "查询角色可访问的权限失败!");
        }
    }

    /**
     * 根据用户id查询角色id
     *
     * @param userId 用户id
     * @return 用户角色id
     */
    @Override
    public ResultBean<List<Long>> selectRoleIdByUserId(Long userId) {
        try {
            List<Long> roleIdList = userRoleRelationMapper.selectRoleIdByUserId(userId);
            return new ResultBean<>(roleIdList);
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, "查询用户角色失败!");
        }
    }

    // 生成树形结构的菜单.
    private List<Menu> getMenuChildren(Menu rootMenu, List<Menu> allMenuList) {
        return allMenuList
                .stream()
                .filter((menu) -> Objects.equals(rootMenu.getId(), menu.getParentId()))
                .collect(Collectors.toList());
    }
    // 生成树形结构的菜单APi.
    private List<BackendApi> getMenuBackendApi(Menu rootMenu) {
        List<BackendApi> backendApiList =menuBackendApiRelationMapper.selectBackendApiListByMenuId(rootMenu.getId())
                .stream()
                .peek(backendApi -> backendApi.setId(backendApi.getId()+10000))
                .collect(Collectors.toList());
        return  backendApiList;
    }
    /**
     * 管理员名称来查找它的密码比对身份
     * 比对成功后重置传入的用户的id
     */
    @Override
    public ResultBean<Integer> resetPassword(Long userId, String password) {
        String rootName = securityUtils.getUsername();
        User rootUser = userMapper.findByUserName(rootName);
        //判断输入的原密码和加密后的密码是否一致
        BCryptPasswordEncoder bc = new BCryptPasswordEncoder();
        boolean matches = bc.matches(password, rootUser.getPassword());
        if (matches) {
            try {
                User user = userMapper.selectByPrimaryKey(userId);
                user.setModifiedGmt(new Date());
                user.setModifiedUser(rootName);
                PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
                user.setPassword(passwordEncoder.encode("123456"));
                userMapper.updateByPrimaryKey(user);
                return new ResultBean<>(-1, 200, "重置用户密码成功!");
            } catch (Exception e) {
                log.error(e.getMessage());
                return new ResultBean<>(-1, 400, "验证成功，但重置用户密码失败!");
            }
        } else {
            return new ResultBean<>(-1, 400, "管理员密码错误!");
        }
    }


    /**
     * 用户修改个人密码
     */
    @Override
    public ResultBean<Integer> changePassword(UserChangePassword userChangePassword) {
        String userName = securityUtils.getUsername();
        User findUser = userMapper.findByUserName(userName);
        //判断输入的原密码和加密后的密码是否一致
        BCryptPasswordEncoder bc = new BCryptPasswordEncoder();
        boolean matches = bc.matches(userChangePassword.getOldPassword(), findUser.getPassword());
        if (matches) {
            try {
                findUser.setModifiedGmt(new Date());
                findUser.setModifiedUser(userName);
                PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
                findUser.setPassword(passwordEncoder.encode(userChangePassword.getNewPassword()));
                userMapper.updateByPrimaryKey(findUser);
                return new ResultBean<>(-1, 200, "用户更改密码成功!");
            } catch (Exception e) {
                log.error(e.getMessage());
                return new ResultBean<>(-1, 400, "验证成功，但更改用户密码失败!");
            }
        } else {
            return new ResultBean<>(-1, 400, "原密码密码错误!");
        }
    }

    /**
     * 用户更换头像
     */
    @Override
    public ResultBean<String> uploadHeadPortrait(MultipartFile file) {
        if (file.isEmpty()) {
            return new ResultBean<>("-1", 400, "上传失败, 请选择文件!");
        }
        String fileName = file.getOriginalFilename();
        String type = fileName != null ? fileName.substring(fileName.lastIndexOf(".")) : ".jpeg";
        String newFileName = UUID.randomUUID().toString() + type;
        File dest = new File("D:\\headPortrait\\" + newFileName);
        boolean isMkdirsSuccess = true;
        if (!dest.exists()) {
            isMkdirsSuccess = dest.mkdirs();
        }
        if (!isMkdirsSuccess) {
            return new ResultBean<>("-1", 400, "在服务器上创建目录失败, 请联系管理员!");
        }
        //读取用户名   查找原img_path   删除旧头像   修改新img_path
        try {
            String userName = securityUtils.getUsername();
            User findUser = userMapper.findByUserName(userName);
            boolean isDelete;
            if (findUser.getImgPath()!=null&& !findUser.getImgPath().equals("")){
                File oldFile = new File("D:\\headPortrait\\" + findUser.getImgPath());
                if (oldFile.exists()) {
                    isDelete = oldFile.delete();
                    if (isDelete) {
                        System.out.println("文件删除成功");
                    } else {
                        System.out.println("文件删除失败");
                    }
                }
            }
            file.transferTo(dest);
            findUser.setImgPath(newFileName);
            userMapper.updateByPrimaryKey(findUser);
            return new ResultBean<>(newFileName, 202, "更换头像成功!");
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>("-1", 400, "上传文件失败, 请联系管理员!");
        }
    }


    /**
     * 根据菜单id查询其可访问的资源
     *
     * @param  menuIdList 菜单id
     * @return 可访问的资源
     */
    public List<Long> selectResourceByMenuId(List<Long> menuIdList) {
            System.out.println("IDList  "+menuIdList);
            List<Long> backendApiList = menuResourceRelationMapper.selectResourceListByMenuId(menuIdList);
            System.out.println("结果"+backendApiList);
            return  backendApiList;
    }
    /**
     * 根据菜单id查询其可访问的backendApi
     *
     * @param  menuId 菜单id
     * @return 可访问的backendApi
     */
    @Override
    public ResultBean<List<BackendApi>> selectBackendApiByMenuId(Long menuId) {
        try {
            List<BackendApi> backendApiList = menuBackendApiRelationMapper.selectBackendApiListByMenuId(menuId);
            return new ResultBean<>(backendApiList);
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, "查询错误,请联系管理员!");
        }
    }

    @Override
    public ResultBean<List<BackendApi>> selectPhoneBackendApi() {
        try {
            List<BackendApi> backendApiList =backendApiMapper.selectPhoneBackendApi();
            return new ResultBean<>(backendApiList);
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, "查询错误,请联系管理员!");
        }
    }

    @Override
    public ResultBean<List<Menu>> selectMenuBackendApiTree(Long roleId) {
        List<Long> menuIdList = roleMenuRelationMapper.selectMenuIdByRoleId(roleId);
        List<Menu> menuList = menuMapper.selectMenuListByMenuIdList(menuIdList);
        try {
            List<Menu> menuTree =
                    menuList
                            .stream()
                            .filter(menu -> menu.getParentId() != null)
                            .filter(menu -> 1 != menu.getParentId())
                            .peek(menu -> menu.setMenuBackendApis(getMenuBackendApi(menu)))
                            .peek(menu -> menu.setFullName(menu.getTitle()))
                            .collect(Collectors.toList());
            return new ResultBean<>(menuTree);
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, "查询菜单错误,请联系管理员!");
        }
    }
}
